package com.jokerpan.project.util;

import com.alibaba.fastjson.JSONObject;
import com.jokerpan.project.entity.Users;
import com.jokerpan.project.mapper.FlowsMapper;
import com.jokerpan.project.mapper.UsersMapper;
import com.jokerpan.project.service.RouteService;
import com.jokerpan.project.service.UsersService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.security.authentication.AnonymousAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component("userTool")
public class UserTool {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    @Resource
    UsersService usersService;
    @Resource
    UsersMapper usersMapper;
    @Resource
    public RedisTemplate redisTemplate;
    @Resource
    RouteService routeService;
    @Resource
    FlowsMapper flowsMapper;

    /**
     *获取当前登录用户信息
     */
    public Users getCurrentUser() {
        ValueOperations<String, String> operations = redisTemplate.opsForValue();
        HttpServletRequest request = ContextHolderUtils.getRequest();
        String tokenHeader = request.getHeader(JwtUtils.TOKEN_HEADER);
        // 如果请求头中没有Bearer信息则直接返回null
        if (tokenHeader == null || !tokenHeader.startsWith(JwtUtils.TOKEN_PREFIX)) {
            return null;
        }
        String token = tokenHeader.replace(JwtUtils.TOKEN_PREFIX, "");
        String username = null;
        Users users = null;
        String key = "user_" + token;
        if (redisTemplate.hasKey(key)){
            log.info("从redis中拿User");
            String userStr = operations.get(key);
            users = JSONObject.parseObject(userStr, Users.class);
            String msgKey = users.getLoginName() + "_messageList";
            String notificationKey = users.getLoginName() + "_notificationList";
            if (redisTemplate.hasKey(msgKey)){
                users.setMessageList(operations.get(msgKey));
            }
            if (redisTemplate.hasKey(notificationKey)){
                users.setNotificationList(operations.get(notificationKey));
            }
        }else {
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            if (!(authentication instanceof AnonymousAuthenticationToken)){
                username = authentication.getName();
                users = usersService.checkLoginName(username);
                List<LinkedHashMap<String, Object>> menuData = routeService.queryAll(users.getRoleId());
                List<LinkedHashMap<String, Object>> fans = flowsMapper.queryFans(users.getId());
                List<LinkedHashMap<String, Object>> follows = flowsMapper.queryFollows(users.getId());
                users.setMenuData(menuData);
                users.setFans(fans);
                users.setFollows(follows);
                String msgKey = users.getLoginName() + "_messageList";
                String notificationKey = users.getLoginName() + "_notificationList";
                if (redisTemplate.hasKey(msgKey)){
                    users.setMessageList(operations.get(msgKey));
                }
                if (redisTemplate.hasKey(notificationKey)){
                    users.setNotificationList(operations.get(notificationKey));
                }
                log.info("从数据库中拿User");
            }
        }
        return users;
    }

    /**
     * 将登陆用户信息存入redis
     */
    public boolean putUserToRedis(){
        String username = null;
        try {
            ValueOperations<String, String> operations = redisTemplate.opsForValue();
            HttpServletRequest request = ContextHolderUtils.getRequest();
            String tokenHeader = request.getHeader(JwtUtils.TOKEN_HEADER);
            String token = tokenHeader.replace(JwtUtils.TOKEN_PREFIX, "");
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            username = authentication.getName();
            Users users = usersService.checkLoginName(username);
            List<LinkedHashMap<String, Object>> menuData = routeService.queryAll(users.getRoleId());
            List<LinkedHashMap<String, Object>> fans = flowsMapper.queryFans(users.getId());
            List<LinkedHashMap<String, Object>> follows = flowsMapper.queryFollows(users.getId());
            users.setMenuData(menuData);
            users.setFollows(follows);
            users.setFans(fans);
            //设置上次登录时间
            Users u = new Users();
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            String now = format.format(new Date());
            u.setId(users.getId());
            u.setLastLoginTime(now);
            users.setLastLoginTime(now);
            usersMapper.update(u);

            String key = "user_" + token;
            if (redisTemplate.hasKey(key)){
                redisTemplate.delete(key);
            }
            String userStr = JSONObject.toJSONString(users);
            //TODO 登录成功后将用户数据放入redis中
            operations.set(key, userStr, 3, TimeUnit.HOURS);
            log.info("存储用户["+ username +"]成功！");
            return true;
        }catch (Exception e){
            log.error("存储用户[" + username + "]失败！" + e.getMessage());
            return false;
        }
    }

    /**
     * 刷新用户信息
     * @return
     */
    public boolean refreshRedis(){
        String username = null;
        try {
            ValueOperations<String, String> operations = redisTemplate.opsForValue();
            HttpServletRequest request = ContextHolderUtils.getRequest();
            String tokenHeader = request.getHeader(JwtUtils.TOKEN_HEADER);
            String token = tokenHeader.replace(JwtUtils.TOKEN_PREFIX, "");
            Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
            username = authentication.getName();
            Users users = usersService.checkLoginName(username);
            List<LinkedHashMap<String, Object>> menuData = routeService.queryAll(users.getRoleId());
            List<LinkedHashMap<String, Object>> fans = flowsMapper.queryFans(users.getId());
            List<LinkedHashMap<String, Object>> follows = flowsMapper.queryFollows(users.getId());
            users.setMenuData(menuData);
            users.setFollows(follows);
            users.setFans(fans);
            String key = "user_" + token;
            if (redisTemplate.hasKey(key)){
                redisTemplate.delete(key);
            }
            String userStr = JSONObject.toJSONString(users);
            Date date = new Date(Instant.now().toEpochMilli() + redisTemplate.getExpire(key) * 1000);
            operations.set(key, userStr);
            redisTemplate.expireAt(key, date);
            log.info("刷新用户["+ username +"]成功！");
            return true;
        }catch (Exception e){
            log.error("刷新用户[" + username + "]失败！" + e.getMessage());
            return false;
        }
    }

    /**
     * 清除当前登录用户信息
     */
    public boolean clearCurrentUser(){
        HttpServletRequest request = ContextHolderUtils.getRequest();
        String tokenHeader = request.getHeader(JwtUtils.TOKEN_HEADER);
        String token = tokenHeader.replace(JwtUtils.TOKEN_PREFIX, "");
        String key = "user_" + token;
        if (redisTemplate.hasKey(key)){
            redisTemplate.delete(key);
        }
        return true;
    }
}
